package com.qiangzi.workflow.engine.bpmn.gateway;

import java.util.List;

import org.dom4j.Element;
import org.springframework.context.ApplicationContext;
import org.springframework.util.Assert;

import com.qiangzi.workflow.engine.bpmn.base.Edge;
import com.qiangzi.workflow.engine.bpmn.base.ProcessInstance;
import com.qiangzi.workflow.engine.bpmn.base.State;
import com.qiangzi.workflow.engine.bpmn.flow.SequenceFlow;

public class ExclusiveGateway extends Gateway {

    // private String defaultFlow;

    // public String getDefaultFlow() {
    // return defaultFlow;
    // }

    public void parse(Element element) throws Exception {

        super.parse(element);

        Assert.isTrue(null != element, "element is null");

        // default属性是可选的,用来保底
        // Attribute defaultAttribute = element.attribute("default");
        // if (null != defaultAttribute) {
        // String defaultVal = defaultAttribute.getText();
        // if (null != defaultVal && defaultVal.length() > 0) {
        // this.defaultFlow = defaultVal;
        // }
        // }
    }

    public Object copy() {
        ExclusiveGateway gateway = new ExclusiveGateway();
        copy(gateway);
        return gateway;
    }

    protected void copy(Object obj) {
        super.copy(obj);

        // ExclusiveGateway gateway = (ExclusiveGateway) obj;
        // gateway.defaultFlow = this.defaultFlow;

    }

    /**
     * 排它网关:每个流必须有条件表达式,依次计算表达式的值,碰到第一个true的执行,其它流忽略; 如果都为false,则引擎抛出异常
     * 
     * @throws Exception
     */
    @Override
    public void invoke(ProcessInstance instance,
                       ApplicationContext applicationContext) throws Exception {

        setState(State.INVOKED);
        LOGGER.debug("node {} state -> invoked", getId());

        // 再处理各个边
        List<Edge> edges = this.getOutgoing();

        if (null == edges) {
            return;
        }

        boolean invokeFound = false;

        for (Edge edge : edges) {

            if (edge instanceof SequenceFlow) {

                // 如果前面已经有表达式计算为true的,则后面的都直接设置为忽略
                if (invokeFound) {
                    edge.ignore(instance);
                    continue;
                }

                edge.invoke(instance, applicationContext);

                // 碰到第一个为true的
                invokeFound = (State.INVOKED == edge.getState());

            } else {
                LOGGER.warn("unknown edge id is {}", edge.getId());
            }
        }

        // 如果全部为忽略,则抛异常
        if (false == invokeFound) {
            throw new Exception(
                "all exclusiveGateway edges expression result -> IGNORED ,id -> " + this.getId());
        }

    }

}
